using System;
using System.Data;
using System.Windows.Forms;

using Tino.Core;

namespace Tino
{
    public class GetTagsCommand : ICommand
    {
        GetTagsCommandDelegate invokeMe;
        int[] checkedTagsIDs;
        ListBox list;

        // Delegate used to retreive tags asynchronously
        delegate DataTable GetTagsCommandDelegate();

        public GetTagsCommand(ListBox List) : this(List, null) { }
        
        public GetTagsCommand(ListBox List, int[] CheckedTagsIDs)
        {
            list = List;
            checkedTagsIDs = CheckedTagsIDs;

            TagElement tagElement = new TagElement();
            invokeMe = new GetTagsCommandDelegate(tagElement.GetTags);
        }

        /// <summary>
        /// Checks weather a given tag must be initially checked
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        bool contains(int id)
        {
            if (checkedTagsIDs == null || checkedTagsIDs.Length == 0)
                return false;

            foreach (int i in checkedTagsIDs)
                if (i == id) return true;

            return false;
        }

        void Callback(IAsyncResult ar)
        {
            // get the dataset as output
            DataTable dt = invokeMe.EndInvoke(ar);

            // update the grid a thread safe fasion!
            MethodInvoker updateList = delegate
            {
                list.BeginUpdate();
                list.Items.Clear();
                foreach (DataRow dr in dt.Rows)
                {
                    int id = Convert.ToInt32(dr["ID"]);
                    string name = (string)dr["Name"];
                    TagsListItem item = new TagsListItem(id, name);
                    list.Items.Add(item);
                    
                    if (contains(id) && list.GetType() == typeof(CheckedListBox))
                        ((CheckedListBox)list).SetItemChecked(list.Items.Count - 1, true);
                }
                list.EndUpdate();
            };

            if (list.InvokeRequired)
            {
                list.Invoke(updateList);
            }
            else
            {
                updateList();
            }
        }

        #region ICommand Members

        public void Execute()
        {
            invokeMe.BeginInvoke(this.Callback, null);
        }

        #endregion
    }
}